#ifndef STATEENGINESTART_H
#define STATEENGINESTART_H

#include "state.h"
#include "stateid.h"
#include "../manager.h"
#include "../eventmanager.h"
#include "../parammanager.h"
#include "../properties.h"

namespace state {

namespace {
const int CUT_TIME = 1000;
const int PHASE4_TIME = 1000;
const int PHASE5_TIME = 2000;
}

struct EngineCut : public State {
	EngineCut(int id) : State(id) {}
	
	virtual void onEnter() {
		Manager::Instance().getEventManager()->setTimer(CUT_TIME);
		
		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, -1);
		p().fcs.brakes.set(Brakes_Value, 1);
		p().fcs.state = getId();
	}
};

struct EngineIdle : public State {
	EngineIdle(int id) : State(id) {}
	
	virtual void onEnter() {
		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, 0);
		p().fcs.brakes.set(Brakes_Value, 0);		
		p().fcs.state = getId();
	}
};

struct EnginePhase1 : public State {
	EnginePhase1(int id) : State(id) {}
	
	virtual void onEnter() {
		int PHASE1_TIME = (int)(Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_TIME1) * 1000);
		float PHASE1_THROTTLE = Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_THR1);

		Manager::Instance().getEventManager()->setTimer(PHASE1_TIME);

		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, PHASE1_THROTTLE, 0.3f);
		p().fcs.brakes.set(Brakes_Value, 1);		
		p().fcs.state = getId();
	}
};

struct EnginePhase2 : public State {
	EnginePhase2(int id) : State(id) {}
	
	virtual void onEnter() {
		int PHASE2_TIME = (int)(Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_TIME2) * 1000);
		float PHASE2_THROTTLE = Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_THR2);

		Manager::Instance().getEventManager()->setTimer(PHASE2_TIME);

		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, PHASE2_THROTTLE, 0.3f);
		p().fcs.brakes.set(Brakes_Value, 1);		
		p().fcs.state = getId();
	}
};

struct EnginePhase3 : public State {
	EnginePhase3(int id) : State(id) {}
	
	virtual void onEnter() {
		int PHASE3_TIME = (int)(Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_TIME3) * 1000);
		float PHASE3_THROTTLE = Manager::Instance().getParamManager()->getFloat(ParamManager::ENGINE_START_THR3);

		Manager::Instance().getEventManager()->setTimer(PHASE3_TIME);

		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, PHASE3_THROTTLE, 0.5f);
		p().fcs.brakes.set(Brakes_Value, 1);		
		p().fcs.state = getId();
	}
};

struct EnginePhase4 : public State {
	EnginePhase4(int id) : State(id) {}
	
	virtual void onEnter() {
		Manager::Instance().getEventManager()->setTimer(PHASE4_TIME);

		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, 0);
		p().fcs.brakes.set(Brakes_Value, 1);		
		p().fcs.state = getId();
	}
};

struct EnginePhase5 : public State {
	EnginePhase5(int id) : State(id) {}
	
	virtual void onEnter() {
		Manager::Instance().getEventManager()->setTimer(PHASE5_TIME);

		PropAccessor p;
		p().fcs.throttle.set(Throttle_Value, 1);
		p().fcs.brakes.set(Brakes_Value, 1);		
		p().fcs.state = getId();
	}
};

struct EngineStart : public State {
	EngineStart() : State() {
		State *cut = new EngineCut(stateid::ENGINE_START);
		State *idle = new EngineIdle(stateid::ENGINE_START);
		State *phase1 = new EnginePhase1(stateid::ENGINE_WARMUP);
		State *phase2 = new EnginePhase2(stateid::ENGINE_WARMUP);
		State *phase3 = new EnginePhase3(stateid::ENGINE_WARMUP);
		State *phase4_1 = new EnginePhase4(stateid::ENGINE_TEST);
		State *phase5_1 = new EnginePhase5(stateid::ENGINE_TEST);
		State *phase4_2 = new EnginePhase4(stateid::ENGINE_TEST);
		State *phase5_2 = new EnginePhase5(stateid::ENGINE_TEST);
		State *phase4_3 = new EnginePhase4(stateid::ENGINE_TEST);
		
		setInitial(cut);

		cut->addTransition(evt_timer, idle);
		idle->addTransition(evt_cmd_auto, phase1);
		idle->addTransition(evt_cmd_abort, cut);
		phase1->addTransition(evt_timer, phase2);
		phase1->addTransition(evt_engine_warmed, phase5_1);
		phase1->addTransition(evt_cmd_abort, cut);
		phase1->addTransition(evt_engine_stopped, cut);
		phase2->addTransition(evt_timer, phase3);
		phase2->addTransition(evt_engine_warmed, phase3);
		phase2->addTransition(evt_cmd_abort, cut);
		phase2->addTransition(evt_engine_stopped, cut);
		phase3->addTransition(evt_timer, phase4_1);
		phase3->addTransition(evt_cmd_abort, cut);
		phase3->addTransition(evt_engine_stopped, cut);
		phase4_1->addTransition(evt_timer, phase5_1);
		phase4_1->addTransition(evt_cmd_abort, cut);
		phase4_1->addTransition(evt_engine_stopped, cut);
		phase5_1->addTransition(evt_timer, phase4_2);
		phase5_1->addTransition(evt_cmd_abort, cut);
		phase5_1->addTransition(evt_engine_stopped, cut);
		phase4_2->addTransition(evt_timer, phase5_2);
		phase4_2->addTransition(evt_cmd_abort, cut);
		phase4_2->addTransition(evt_engine_stopped, cut);
		phase5_2->addTransition(evt_timer, phase4_3);
		phase5_2->addTransition(evt_cmd_abort, cut);
		phase5_2->addTransition(evt_engine_stopped, cut);
		phase4_3->addTransition(evt_timer, NULL);
		phase4_3->addTransition(evt_cmd_abort, cut);
		phase4_3->addTransition(evt_engine_stopped, cut);
	}

	virtual void onEnter() {
		PropAccessor p;
		p().fcs.roll.set(Roll_Neutral);
		p().fcs.pitch.set(Pitch_Neutral);
		p().fcs.yaw.set(Yaw_Neutral);
		p().fcs.flaps.set(Flaps_Value, Flaps_Value_Retracted);
		p().fcs.brakes.set(Brakes_Value, 0);

		p().fcs.parachute_armed = false;
	}
};

}

#endif
